package org.easiermock;

import java.lang.reflect.Method;

import org.aopalliance.intercept.MethodInvocation;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

public class CountingMethodListenerTest {
	
	private static final String TEST_ID1 = "id1";
	private static final String TEST_ID2 = "id2";
	private CountingMethodListener countingMethodListener;
	private MethodInvocation mockMethod1Invocation;
	private MethodInvocation mockMethod2Invocation;

	@Before
	public void setUp() throws Exception {
		countingMethodListener = new CountingMethodListener();
		Method mockMethod1 = MockObject.class.getMethod("mockMethod1", new Class[0]);
		Method mockMethod2 = MockObject.class.getMethod("mockMethod2", new Class[0]);
		MockObject mockInstance = new MockObject();
		mockMethod1Invocation = AopUtil.createMethodInvocation(mockInstance, mockMethod1, new Object[0]); 
		mockMethod2Invocation = AopUtil.createMethodInvocation(mockInstance, mockMethod2, new Object[0]); 
	}
	
	@Test
	public void testIncrement() {
		Assert.assertEquals(0, countingMethodListener.getBeforeCount(TEST_ID1));
		Assert.assertEquals(0, countingMethodListener.getBeforeCount(TEST_ID2));
		countingMethodListener.beforeInvocation(mockMethod1Invocation);
		Assert.assertEquals(1, countingMethodListener.getBeforeCount(TEST_ID1));
		Assert.assertEquals(0, countingMethodListener.getBeforeCount(TEST_ID2));
		countingMethodListener.beforeInvocation(mockMethod1Invocation);
		Assert.assertEquals(2, countingMethodListener.getBeforeCount(TEST_ID1));
		Assert.assertEquals(0, countingMethodListener.getBeforeCount(TEST_ID2));
	}
	
	@Test
	public void testReset() {
		countingMethodListener.beforeInvocation(mockMethod1Invocation);
		countingMethodListener.beforeInvocation(mockMethod2Invocation);
		Assert.assertEquals(1, countingMethodListener.getBeforeCount(TEST_ID1));
		Assert.assertEquals(1, countingMethodListener.getBeforeCount(TEST_ID2));
		countingMethodListener.reset(TEST_ID1);
		Assert.assertEquals(0, countingMethodListener.getBeforeCount(TEST_ID1));
		Assert.assertEquals(1, countingMethodListener.getBeforeCount(TEST_ID2));
		countingMethodListener.reset(TEST_ID2);
		Assert.assertEquals(0, countingMethodListener.getBeforeCount(TEST_ID1));
		Assert.assertEquals(0, countingMethodListener.getBeforeCount(TEST_ID2));
		countingMethodListener.beforeInvocation(mockMethod1Invocation);
		Assert.assertEquals(1, countingMethodListener.getBeforeCount(TEST_ID1));
		Assert.assertEquals(0, countingMethodListener.getBeforeCount(TEST_ID2));
	}
	
	@Test
	public void testResetAll() {
		countingMethodListener.beforeInvocation(mockMethod1Invocation);
		countingMethodListener.beforeInvocation(mockMethod2Invocation);
		Assert.assertEquals(1, countingMethodListener.getBeforeCount(TEST_ID1));
		Assert.assertEquals(1, countingMethodListener.getBeforeCount(TEST_ID2));
		countingMethodListener.resetAll();
		Assert.assertEquals(0, countingMethodListener.getBeforeCount(TEST_ID1));
		Assert.assertEquals(0, countingMethodListener.getBeforeCount(TEST_ID2));
	}
	
	static class MockObject {
		@Mock(id=TEST_ID1)
		public void mockMethod1() {
			// No impl required
		}
		@Mock(id=TEST_ID2)
		public void mockMethod2() {
			// No impl required
		}
	}
}
